package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 自定义切面，实现公共字段自动填充处理逻辑
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {


    //    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
//     加上代表谁缩小范围 不加也行
    /*
    切入点
     */
    @Pointcut("@annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointcut(){}
    /**
     * 前置通知，在通知中进行公共字段的赋值
     */
    @Before("autoFillPointcut()")//对加了这个@AutoFill注解方法进行增强
    public void autoFill(JoinPoint joinPoint){//joinPoint 被增强的原始方法
        //获取被增强方法的方法签名
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        // 通过增强方法签名 获取方法对象
        Method method = signature.getMethod();
        // method指的是被增强方法对象  比如insert update这些方法对象
        // 获取注解
        AutoFill autoFill = method.getAnnotation(AutoFill.class);
        OperationType operationType = autoFill.value();

        log.info("开始进行公共字段自动填充");
        //自动填充目标要确定  原始方法的参数 实体对象  可能是 Employee Category Dish SetMeal
        //拿到参数 对象 进行 功能的增强
        Object[] args = joinPoint.getArgs();
        if(args==null || args.length==0){
            //说明 参数没有或者有问题
            return;//没有必要增强 因为没有目标了！！！！
        }

        Object entry = args[0];// entry 就是要增强的对象
        // 准备赋值的数据
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();
        // 我得知道  增强的是添加还是更新
        if(operationType== OperationType.INSERT){//标明是新增
            log.info("这里判断出来是新增");
            // 做四个字段增强 --- 自动填充 四个字段 属性值
            //  已知实体对象 entry 里面有个属性叫 createTime  且有set方法
            try {

//            Method setCreateTime = entry.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);
                Method setCreateTime = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method setUpdateTime = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setCreateUser = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER,Long.class);
                Method setUpdateUser = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                //反射形式执行方法
                setCreateTime.invoke(entry,now);//  entry.setCreateTime(now)
                setUpdateTime.invoke(entry,now);
                setCreateUser.invoke(entry,currentId);
                setUpdateUser.invoke(entry,currentId);

            } catch (Exception e) {
                e.printStackTrace();
                log.info("没有对应set方法");
            }

        }else{//更新
            log.info("这里判断出来是更新");
            // 做两个字段的增强--- 自动填充 两个个字段 属性值
            try {

                Method setUpdateTime = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                //反射形式执行方法
                setUpdateTime.invoke(entry,now);
                setUpdateUser.invoke(entry,currentId);

            } catch (Exception e) {
                e.printStackTrace();
                log.info("没有对应set方法");
            }
        }
    }
}
